home *** CD-ROM | disk | FTP | other *** search
/ Cracking 1 / Cracking I..iso / Tools / Ostatní / aPLib v0.26b / examples / 16bit / depptiny.nas < prev    next >
Encoding:
Text File  |  2001-12-15  |  14.8 KB  |  281 lines

  1. ;;
  2. ;; aPLib compression library  -  the smaller the better :)
  3. ;;
  4. ;; NASM 16bit assembler tiny depacker example
  5. ;;
  6. ;; Copyright (c) 1998-2000 by Joergen Ibsen / Jibz
  7. ;; All Rights Reserved
  8. ;;
  9. ;; -> 16bit by METALBRAIN (metalb@bart.us.es)
  10. ;;
  11.  
  12.                 org     256
  13.  
  14.                 cld                     ;Clear direction flag for safety
  15.                 mov     ah,4ah          ;Modify memory block size (on start,
  16.                                         ; the .COM program is given all free
  17.                                         ; memory, but this could be less than
  18.                                         ; the needed amount (162K). As a nice
  19.                                         ; side effect, we are freeing unused
  20.                                         ; memory, but who cares under DOS?
  21.                 mov     bh,41           ;Number of needed paragraphs
  22.                                         ; (rounded up)
  23.                 call    int_n_check     ;Resize or exit if error
  24.  
  25.                 mov     si,129          ;Arguments from PSP start here
  26.                 mov     di,testitnow    ;This will be called quite a few times
  27.                                         ; and later will be used to place
  28.                                         ; variables
  29. space1          call    di              ;Parse...
  30.                 jz      space1          ;Search for non-space
  31.                 dec     si              ;Found: here start infile name
  32.                 mov     dx,si           ;Keep it in DX
  33. space2          call    di              ;Keep parsing
  34.                 jnz     space2          ;Till a space appears
  35.                 mov     [si-1],dh       ;Make infile ASCIIZ
  36. space3          call    di
  37.                 jz      space3          ;Now search a non-space again
  38.                 dec     si              ;Here start outfile name
  39.                 push    si              ;Keep it in stack
  40. space4          lodsb                   ;Final parse
  41.                 cmp     al," "
  42.                 ja      space4          ;Space or below means end of filename
  43.                 mov     [si-1],dh       ;Make ASCIIZ this one too
  44.                 mov     ax,3d00h        ;Function to open infile
  45.                 call    int_n_check     ;Try it
  46.                 stosw                   ;Store infile handle at handlein
  47.                 mov     dx,tmpname
  48.                 xor     cx,cx
  49.                 mov     ah,3ch
  50.                 call    int_n_check     ;Create temporal outfile: "NOT OK$"
  51.                 stosw                   ;Store temporal outfile handle
  52.                 xchg    ax,dx           ;And place it in DX
  53.                 xor     ebx,ebx         ;EBX=0
  54.                 pop     si              ;Pop outfile name address from stack
  55.                 mov     bh,8            ;BX=inbuff
  56.                 mov     esp,ebx         ;Set stack before inbuff
  57.                 mov     bx,es           ;Segment
  58.                 add     bh,8            ; +32K
  59.                 imul    eax,ebx,byte 16 ;32 bit start of segment address+32K
  60.                 add     eax,esp         ;EAX=freemem 32 bit address
  61.                 push    si              ;Push again outfile name address
  62.                 push    dx              ;Also store temporal outfile handle
  63.                 mov     dl,128          ;Reset bit counter in DL, and DX=0080h
  64.                 mov     cl,3            ;Set EAX at freemem32, origin32 and
  65.                 rep     stosd           ;  limit32
  66.                 add     [di-2],byte 2   ;Now limit32=freemem32+128K
  67.                 add     [di-7],dx       ;Now origin32=freemem32+32K
  68.                 xchg    eax,edi         ;Set freemem32 at EDI
  69.                 mov     esi,edi         ;And ESI
  70.                                         ;Starting point for DEPACK16
  71.                 push    edi             ;Store freemem32
  72. literal         call    getesi          ;Copy a byte from [esi] to [edi]
  73. putedi_nexttag  call    putedi
  74.                 call    newtest         ;Here EAX=0
  75.                 jmp     short nexttag   ;Skip next part
  76.  
  77. normalcodepair  xchg    ax,cx           ;High part of distance in AX
  78.                 dec     ax              ;Subtract 1. Min value is 0
  79.                 shl     eax,8           ;EAX=00dddd00h
  80.                 call    getesi          ;Fill distance in AL
  81.                 call    getgamma        ;Take gamma encoded ECX
  82.                 cmp     eax,32000
  83.                 jae     domatch_with_2inc ;Above 31999: ECX+=2
  84.                 cmp     ah,5
  85.                 jae     domatch_with_inc ; 1279<EAX<32000: ECX=+1
  86.                 cmp     ax,byte 127
  87.                 ja      domatch         ;EAX<128: ECX+=2
  88. domatch_with_2inc
  89.                 inc     ecx
  90. domatch_with_inc
  91.                 inc     ecx
  92. domatch         xchg    eax,ebp         ;Store EAX in EBP
  93. domatch_R0      mov     eax,ebp         ;Take EAX from last EBP
  94. domatch_continue
  95.                                         ;Here EAX=match distance
  96.                                         ;     ECX=match lenght
  97.                 push    esi             ;Store current read pointer
  98.                 mov     esi,edi
  99.                 sub     esi,eax         ;ESI=EDI-EAX > origin pointer
  100.                 cmp     esi,[freemem32] ;Test for bad infile #1: Limit crossed
  101.                 call    finerr01        ;Exit if error
  102. repmovsb        call    dontread        ;getesi without checking limit
  103.                 call    putedi          ;and with putedi completes the movsb
  104.                 mov     ah,128          ;Here EAX=32768 (in case of writing
  105.                 call    newtest         ;  data, update esi too)
  106.                 loop    repmovsb,ecx    ;Do it ecx times
  107.                 pop     esi             ;Recover read pointer
  108. nexttag         call    getbit          ;Get a bit
  109.                 jnc     literal         ;0: literal, go for it
  110.                 xor     ecx,ecx         ;Clear ECX
  111.                 xor     ax,ax           ;and AX
  112.                 call    getbit          ;Get another bit
  113.                 jnc     codepair        ;10: codepair, go for it
  114.                 call    getbit          ;Get yet another one
  115.                 jnc     shortmatch      ;110: shortmatch
  116.                 mov     al,16           ;Set marker bit
  117.                 inc     cx              ;CX=1
  118. getmorebits     call    getbit          ;Get a bit
  119.                 adc     al,al           ;Set it in AL
  120.                 jnc     getmorebits     ;Do it till marker is out (4 times)
  121.                 jnz     domatch_continue ; 111xxxx > continue, AL has distance
  122.                 jmp     short putedi_nexttag    ;1110000: Put a zero byte
  123.  
  124. codepair        call    getgamma        ;Get gamma encoded first part of
  125.                                         ; distance in CX. Min value is 2
  126.                 dec     cx              ;\Subtract 2, if not zero then
  127.                 loop    normalcodepair  ;/continue with distance
  128.                 push    word domatch_R0 ;Get gamma encoded lenght in ECX then
  129.                                         ; jump to domatch_R0 (use last
  130.                                         ; distance)
  131.  
  132. getgamma        inc     cx              ;First bit is always 1
  133. getgammaloop    call    getbit          ;Get next bit
  134.                 adc     ecx,ecx         ;Put it in ECX
  135.                 call    getbit          ;Get gamma bit
  136.                 jc      getgammaloop    ;If it's 1, continue growing ECX
  137.                 ret
  138.  
  139. shortmatch      call    getesi          ;Get a byte
  140.                 shr     ax,1            ;Distance = AL/2, Lenght in carry flag
  141.                 jz      donedepacking   ;If zero, end packing
  142.                 adc     cx,cx           ;Lenght = 1 or 0
  143.                 jmp     short domatch_with_2inc ; Decode with lenght 2 or 3
  144.  
  145. donedepacking   pop     esi             ;ESI=freemem32
  146.                 pop     bx              ;Get outfile handle
  147.                 sub     edi,esi         ;And here finish DEPACK 16
  148.                                         ;Now edi has the number of depacked
  149.                                         ; bytes left to be written
  150.                 push    ds              ;Preserve data segment
  151.                 mov     ch,080h         ;Write using 32K chunks to enable
  152.                                         ; the sign optimization
  153.                 mov     dx,freemem      ;Flush everything from here to end
  154. more            cmp     edi,ecx
  155.                 ja      notlast         ;If EDI > 32K, write 32K bytes
  156.                 mov     cx,di           ;If EDI < 32K, write EDI bytes
  157. notlast         call    writefile       ;Write chunk
  158.                 mov     ax,ds
  159.                 add     ah,8
  160.                 mov     ds,ax           ;Advance 32K
  161.  
  162.                 sub     edi,ecx         ;Update number of bytes to be written
  163.                 ja      more            ;Above zero, continue writing
  164.                 pop     ds              ;Recover data segment
  165.                 push    ds
  166.                 pop     es              ;Set es=ds
  167.                 pop     dx              ;Get pointer to outfile name
  168.                 call    close_del       ;Close temporal outfile and try to
  169.                                         ; delete the file named with our
  170.                                         ; outfile name, in case it exists
  171.                 jnc     renameit        ;If that file existed and was deleted,
  172.                                         ; go ahead and rename the temporal one
  173.                 cmp     al,5            ;If it didn't exist, rename it too
  174.                 jz      finerr          ;But if error was for other reason,
  175.                                         ; exit with NOT OK
  176. renameit        mov     ah,56h
  177.                 mov     di,dx
  178.                 mov     dx,tmpname
  179.                 call    int_n_check     ;Rename temporal outfile to outfile
  180.                 mov     dx,noerr        ;Final message: OK
  181. final_dxok      mov     ah,9
  182.                 int     33              ;Show final message
  183.                 int     20h             ;Exit program
  184.  
  185. writefile       mov     ah,40h
  186.                 call    int_n_check     ;Write
  187.                 dec     ax
  188.                 jns     not_finerr      ;If disk isn't full there's no error
  189. finerr          mov     dx,tmpname      ;Error message: NOT OK
  190.                 push    word final_dxok ;Return point
  191. close_del       mov     ah,3eh
  192.                 int     33              ;Close temporal outfile
  193.                 mov     ah,41h
  194.                 int     33              ;Delete outfile (when called to
  195.                                         ; close_del) or temporal outfile
  196. not_finerr      ret                     ; (when we fall from finerr)
  197.  
  198. getesi          cmp     esi,[freemem32] ; If esi is at freemem32, we must
  199.                 jnz     dontread        ;load 32k of compressed data
  200.                 pushad                  ;Keep all registers (32bit because
  201.                 mov     ah,3fh          ; DOS function may modify EAX!!!)
  202.                 mov     bx,[handlein]   ;Take infile handle
  203.                 mov     cx,32768        ;Number of bytes
  204.                 mov     dx,inbuff       ;Place to read
  205.                 call    int_n_check     ;Read and exit if error
  206.                 dec     ax              ;---Test for bad infile #2: 0 bytes
  207.                 popad                   ;\/  read (a good infile will finish
  208.                 js      finerr          ;/\  and won't ask for more data)
  209.                                         ;  >Restore registers
  210.                 sub     esi,32768       ;esi at beginning of buffer again
  211. dontread        push    esi             ;----->Emulates mov al,[esi] in 16 bit
  212.                 pop     bx              ;    /   code (as mov al,[esi] gives
  213.                 pop     bx              ;   /    a nasty fault)
  214.                 ror     bx,4            ;  /
  215.                 mov     es,bx           ; /
  216.                 mov     al,[es:si]      ;/
  217.                 inc     esi             ;Update read pointer
  218.                 ret
  219.  
  220. int_n_check     int     33              ;Perform operation (depends on AH)
  221. finerr01        jc      finerr          ;If it failed, exit with NOT OK
  222.                 ret
  223.  
  224. getbit          add     dl,dl           ;Get a tag bit
  225.                 jnz     stillbitsleft   ;If zero, that bit was the marker, so
  226.                                         ; we must read a new tag byte from
  227.                 xchg    ax,dx           ;\ the infile buffer
  228.                 call    getesi          ; >Emulate mov dl,[esi], inc esi
  229.                 xchg    ax,dx           ;/
  230.                 stc                     ;Carry flag is end marker
  231.                 adc     dl,dl           ;Get first bit and set marker
  232. stillbitsleft   ret                     ;Return with bit read in flag C
  233.  
  234. newtest         cmp     edi,[limit32]   ;Check if we've run out of memory
  235.                 jc      endtest         ;NO: end test
  236.                 pushad                  ;Keep registers
  237.                 mov     dx,freemem
  238.                 mov     cx,32768
  239.                 mov     bx,[handletmp]
  240.                 call    writefile       ;Write 32K of data
  241.                 mov     ecx,edi
  242.                 mov     esi,[origin32]
  243.                 sub     ecx,esi         ;ECX=number of bytes to be moved
  244.                 mov     edi,[freemem32] ;Output data will be moved 32K back
  245. otherrepmovsb   call    getesi          ;  \
  246.                 call    putedi          ;   >Emulates rep movsb
  247.                 loop    otherrepmovsb,ecx ;/
  248.                 popad                   ;Restore registers
  249.                 sub     esi,eax         ;Update read pointer (sub 32K if
  250.                                         ;   we are in the repmovsb loop)
  251.                 mov     ah,128          ;EAX=32K
  252.                 sub     edi,eax         ;Update write pointer
  253. endtest         ret
  254.  
  255. putedi          push    edi             ;----->Emulate mov [edi],al in 16 bit
  256.                 pop     bx              ;    /  code (as mov [edi],al gives
  257.                 pop     bx              ;   /   a nasty fault)
  258.                 ror     bx,4            ;  /
  259.                 mov     es,bx           ; /
  260.                 mov     [es:di],al      ;/
  261.                 inc     edi             ;Update write pointer
  262.                 xor     eax,eax         ;Clear EAX
  263.                 ret
  264.  
  265. tmpname         db      "NOT "
  266. noerr           db      "OK$",0
  267.  
  268. testitnow       lodsb                   ;Parse one byte
  269.                 cmp     al,32           ;Is it space?
  270.                 jc      finerr01        ;Below space: bad arguments > exit
  271.                 ret
  272.  
  273. handlein        EQU     testitnow
  274. handletmp       EQU     testitnow+2
  275. freemem32       EQU     testitnow+4
  276. origin32        EQU     testitnow+8
  277. limit32         EQU     testitnow+12
  278.                                         ;Stack is between program and 1280
  279. inbuff          EQU     2048            ;Place for 32K infile reading buffer
  280. freemem         EQU     inbuff+32768
  281.